
package com.learn.command;

import com.learn.service.TestService;
import com.netflix.hystrix.*;
import lombok.extern.slf4j.Slf4j;

import java.util.Random;

/**
 * 普通的HystrixCommand，实现了fallback方法
 */
@Slf4j
public class SimpleHystrixCommand extends HystrixCommand<String> {

	private TestService testService;

	public SimpleHystrixCommand(TestService testService) {
		super(setter());
		this.testService = testService;
    }

    @Override
	protected String run() throws Exception {
		String s = testService.getResult();
		log.info("get thread local:{}",s);

		/**
		 * 如果睡眠时间，超过2s，会降级
		 * {@link #getFallback()}
		 */
		int millis = new Random().nextInt(3000);
		log.info("will sleep {} millis",millis);
		Thread.sleep(millis);

		return s;
	}

	private static Setter setter() {

		// 服务分组
		HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("members");
		// 服务标识
		HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("member");
		// 线程池名称
		HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("member-pool");

		// 线程池配置 线程池大小为10,线程存活时间15秒 队列等待的阈值为100,超过100执行拒绝策略
		HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter().withCoreSize(10)
				.withKeepAliveTimeMinutes(15).withQueueSizeRejectionThreshold(100);

		// 命令属性配置Hystrix 开启超时
		HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()
				// 采用线程池方式实现服务隔离
				.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
				/**
				 * 执行时间，2s，2s执行不完成，算超时，会降级
				 */
				.withExecutionTimeoutEnabled(true)
				.withExecutionTimeoutInMilliseconds(2000);

		return Setter.withGroupKey(groupKey).andCommandKey(commandKey).andThreadPoolKey(threadPoolKey)
				.andThreadPoolPropertiesDefaults(threadPoolProperties).andCommandPropertiesDefaults(commandProperties);

	}

	/**
	 * 执行业务方法超时时，会进入本方法进行降级
	 * @return
	 */
	@Override
	protected String getFallback() {

		log.error("fallback occur");
		return "fallback occur";
	}
}
